package cn.kgc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.kgc.entity.Menus;
import cn.kgc.entity.MetaVo;
import cn.kgc.entity.RolesMenus;
import cn.kgc.entity.RouterVo;
import cn.kgc.mapper.MenusMapper;
import cn.kgc.service.MenusService;
import cn.kgc.service.RolesMenusService;
import cn.kgc.util.SystemConstant;
import cn.kgc.util.SystemUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wangyue
 * @version 1.0
 */
@Slf4j
@Service("menusService")
@SuppressWarnings("all")
public class MenusServiceImpl extends ServiceImpl<MenusMapper, Menus> implements MenusService {
    @Resource
    private RolesMenusService rolesMenusService;

    @Override
    public List<RouterVo> getRouterVoList() {
        Integer roleId = SystemUtil.getLoginUser().getRoleId();
        LambdaQueryWrapper<RolesMenus> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RolesMenus::getRid, roleId);
        List<RolesMenus> list = rolesMenusService.list(wrapper);
        //根据菜单的id获得对应菜单信息
        List<Integer> mids = list.stream().map(RolesMenus::getMid).collect(Collectors.toList());
        List<Menus> menus = this.listByIds(mids);
        //可以不加以下代码
        if (CollUtil.isEmpty(menus)) {
            return List.of();
        }
        //将菜单转为树形集合
        menus = SystemUtil.tree(menus);
        //将菜单的信息转为路由信息
        return generateRouterVo(menus);
    }

    private List<RouterVo> generateRouterVo(List<Menus> menus) {
        List<RouterVo> routerVos = new ArrayList<>();
        for (Menus menu : menus) {
            //每个菜单对应一个路由信息
            RouterVo routerVo = new RouterVo();
            //如果当前菜单是按钮类型
            if (menu.getMenuType() == SystemConstant.MENU_TYPE_BUTTON) {
                //并且此按钮没有路由组件，不需要将此按钮转为路由信息,所以进入下次循环
                if (StrUtil.isBlank(menu.getComponent())) {
                    continue;
                }
                //并且按钮是有路由组件，将此按钮转为路由信息，所以进入下次循环
                routerVo.setHide(true);
            }
            //将菜单的信息保存到路由当中
            BeanUtil.copyProperties(menu, routerVo);
            routerVo.setName(menu.getMenuName());
            MetaVo metaVo = new MetaVo();
            metaVo.setTitle(menu.getMenuName());
            routerVo.setMeta(metaVo);
            //判断当前菜单(或按钮)是否有子菜单，如果有子菜单
            if (CollectionUtil.isNotEmpty(menu.getChildren())) {
                //则子菜单转为路由信息
                List<RouterVo> tempRouterVos = generateRouterVo(menu.getChildren());
                //将子菜单的路由信息放到当前的路由对象中
                routerVo.setChildren(tempRouterVos);
            }
            //将路由信息保存到routerVos
            routerVos.add(routerVo);
        }
        return routerVos;
    }
    // 1 如果菜单类型是按钮，需要判断下按钮路由组件是否为空，不为空的话，我们也要将按钮转为路由信息
    // 因为有些按钮，就是用来进行页面跳转的。但是这些按钮不能在菜单上显示，需要将这些按钮隐藏掉

    // 2 如果按钮组件为空，不需要将这些按钮保存到路由中了

    // 3 如果菜单类型是菜单，那么需要将菜单转为路由信息


    @Override
    public List<String> getMenuPerms() {
        Integer roleId = SystemUtil.getLoginUser().getUserId();
        List<Menus> menus = findMenusByRoleId(roleId);
        return menus.stream()
                .filter(menu -> menu.getMenuType() == SystemConstant.MENU_TYPE_BUTTON)
                .map(menu -> menu.getPerm())
                .collect(Collectors.toList());
    }

    public List<Menus> findMenusByRoleId(int roleId) {
        //1 根据角色id查询角色下的菜单信息
        LambdaQueryWrapper<RolesMenus> wrapper = new LambdaQueryWrapper<RolesMenus>();
        wrapper.eq(RolesMenus::getRid, roleId);
        //根据角色id查询角色拥有的菜单的id
        List<RolesMenus> rolesMenus = rolesMenusService.list(wrapper);
        //根据菜单的id查询菜单的信息(菜单的父级菜单id)
        List<Menus> menus = rolesMenus.stream().map(roleMenu -> {
            return getById(roleMenu.getMid());
        }).collect(Collectors.toList());
        //2 剔除掉菜单中的父菜单
        //创建新的集合 集合中包含菜单的信息
        List<Menus> tempMenus = CollUtil.newArrayList(menus);
        menus.forEach(menu -> {
            //如果菜单的id等于另一个菜单的父id说明当前菜单是一个父级菜单 剔除父级菜单
            tempMenus.removeIf(tempMenu ->
                    tempMenu.getId().longValue() == menu.getParentId().longValue());
        });
        return tempMenus;
    }

    @Override
    public List<SimpleGrantedAuthority> getAuthorityByRoleId(int roleId) {
        //获得角色拥有的菜单集合
        List<Menus> menusByRoleId = findMenusByRoleId(roleId);

        return menusByRoleId.stream()
                //过滤出菜单类型是按钮的菜单
                .filter(menus -> menus.getMenuType() == SystemConstant.MENU_TYPE_BUTTON)
                //将上一步过滤出来的按钮对象转为权限对象，权限对象中封装按钮的权限标识符
                .map(menus -> new SimpleGrantedAuthority(menus.getPerm()))
                .collect(Collectors.toList());

    }
}
